old_posts/2016-7-15-Implementing Client-side Encryption with Azure Mobile Apps.html (89 lines of code) (raw):
---
layout: post
hide_excerpt: true
---
<html><head>
<meta charset="utf-8"/>
</head>
<body>
<div id="page">
<a class="url fn n profile-usercard-hover" href="https://social.msdn.microsoft.com/profile/Adrian Hall (MSFT)" target="_blank">Adrian Hall (MSFT)</a>
<time> 7/15/2016 11:09:26 AM</time>
<hr/>
<div id="content"><a href="https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-value-prop/" target="_blank">Azure Mobile Apps</a> provides an offline sync feature that makes it easy to build mobile apps that work without a network connection. When apps use this feature, end users can still create and modify data, even when the app is in an offline mode. The changes are saved to a local store and can be synced to your Mobile App backend when the app is back online. See <a href="https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-offline-data-sync" target="_blank">Offline Data Sync in Azure Mobile Apps</a> for more details.
Offline sync uses a <a href="https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-offline-data-sync/#what-is-a-local-store" target="_blank">local store</a> to persist data on the client device, where the specific storage implementation can be customized. The Mobile Apps client SDK provides local stores based on SQLite (Windows, Xamarin, and Android) and Core Data (iOS native). SQLite does not have any built-in encryption support, but there are a number of extensions that provide encryption. One such extension is the <a href="http://www.hwaci.com/sw/sqlite/see.html" target="_blank">SQLite Encryption Extension</a> (SEE). SEE is an add-on to the public domain version of SQLite and does not require a custom local store implementation. Note that SEE is not the only encryption option for Mobile Apps; For instance, you can define a local store that uses <a href="https://www.zetetic.net/sqlcipher/documentation/" target="_blank">SQLCipher</a> for encryption.
This sample requires you to purchase a license for SEE. This is not included as part of the Azure Mobile Apps Client SDK.
In this article I will walk through a sample to show how to create an encrypted local store using SEE in a Xamarin.Android app - this can be done in three parts:
<ol>
<li>Build the Quickstart for Xamarin.Android and enable offline sync</li>
<li>Build sqlite3.dll with SEE for Android</li>
<li>Update the Quickstart to use custom version of sqlite3</li>
</ol>
The Quickstart for Azure Mobile Apps builds a simple task list. You can follow the <a href="https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-android-get-started/" target="_blank">Getting Started tutorial for Xamarin.Android</a> and then <a href="https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-xamarin-android-get-started-offline-data/" target="_blank">Enable Offline Sync</a> in your quickstart app.
<h3>Build SQLite with SEE Support for Android</h3>
The <a href="http://www.hwaci.com/sw/sqlite/see.html" target="_blank">SQLite Encryption Extension</a> is a commercial encryption product and you must <a href="http://www.hwaci.com/cgi-bin/see-step1" target="_blank">buy a license</a> for SEE before continuing. After purchase, you may <a href="https://www.sqlite.org/android/doc/trunk/www/install.wiki#obtaincode" target="_blank">download the code</a> for building SQLite for Android and <a href="https://www.sqlite.org/android/doc/trunk/www/see.wiki" target="_blank">build the native SQLite3 library with SEE</a>. By default, the native library is build for the armeabi platform - common for actual Android devices. You will need to build the native app for an x86 platform if you wish to run your modified app on the <a href="https://www.visualstudio.com/en-us/features/msft-android-emulator-vs.aspx" target="_blank">Visual Studio Emulator for Android</a>. To do this, open a Visual Studio command prompt and do the following:
<pre>cd SQLite_Android_Bindings\sqlite3\src\main
ndk-build.cmd APP_ABI=x86</pre>
Adjust the paths above as appropriate for your environment. Once built, you can open your Quickstart project in Visual Studio and copy the generated native library for x86 from <tt>SQLite_Android_Bindings\sqlite3\src\main\libs\x86</tt> to <tt>YourQuickstartProject\lib\x86</tt>. Finally, update the build action for the copied <tt>libsqliteX.so</tt> file to be <strong>AndroidNativeLibrary</strong>:
<a href="{{ site.baseurl }}/media/2016/07/2016-07-06_15h45_34.png" rel="attachment wp-att-855"><img alt="2016-07-06_15h45_34" class="alignnone size-medium wp-image-855" height="218" src="{{ site.baseurl }}/media/2016/07/2016-07-06_15h45_34-300x218.png" width="300"/></a>
<h3>Build and Run the Quickstart</h3>
Before we can build the Quickstart, we need to configure the build environment to include the modified sqliteX DLL instead of the normal sqlite3.dll system library that is a part of the Android platform. Add an <tt>app.config</tt> file to your project with the following:
<pre>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<dllmap dll="sqlite3" target="libsqliteX.so" />
</configuration>
</pre>
Any <a href="https://msdn.microsoft.com/en-us/library/aa446536.aspx" target="_blank">P/Invoke operations</a> that would normally load the sqlite3.dll will now be mapped to load the libsqliteX.so file that we provide. The <a href="https://sqlitepcl.codeplex.com/" target="_blank">SQLitePCL library</a> that is used by the Azure Mobile Apps Offline Client SDK uses P/Invoke to call the native methods within sqlite3.dll, so this will now automatically reference the sqliteX library.
This configuration file needs to be included in the APK package. This only happens when the <tt>EmbedAssembliesIntoApk</tt> is set to true in your csproj file. This property is set to false by default when using a debug build. When debugging the app, ensure you set the <tt>EmbedAssembliesIntoApk</tt> to true. Edit the csproj file and add the following to it:
<pre><EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk></pre>
It's a good idea to do this edit from a normal text editor and then load it into Visual Studio. For an example, see the <a href="https://github.com/Azure-Samples/app-service-mobile-dotnet-offline-encryption" target="_blank">sample on GitHub</a>.
We can now create a local encrypted SQLite database protected by a password for use with offline sync. Create a <tt>MobileServiceSQLiteStore</tt> as normal, but specify a file Uri with a query parameter that includes the password. Here is the modified code that initialized the local store:
<pre>/// <summary>
/// Converts a string to a hex key
// </summary>
private string StringToHex(string hexstring)
{
var sb = new StringBuilder();
foreach (char t in hexstring)
{
sb.Append(Convert.ToInt32(t).ToString("x") + " ");
}
return sb.ToString();
}
private async Task InitLocalStoreAsync()
{
// WARNING: Do not hard code passwords in your application!
var password = "Hello";
if (!Utils.MobileService.SyncContext.IsInitialized)
{
// Generate the URI to the offline cache file
var hexkey = StringToHex(password);
var offlineCacheUri = new System.Uri(Path.Combine(ApplicationData.Current.LocalFolder.Path,"testSee.db"));
string offlineCache = $"{offlineCacheUri.AbsoluteUri}?hexkey={hexkey}";
// Set up the encrypted SQLite Store as normal
var store = new MobileServiceSQLiteStore(offlineCache);
store.DefineTable<TodoItem>();
await Utils.MobileService.SyncContext.InitializeAsync(store);
}
// Synchronize the offline cache with the server
await SyncAsync();
}
</pre>
Once the local database is created with a password, it is encrypted. If you try to use that database without providing a valid password, it would fail (throwing an Exception) with the error message ‘Error: file is encrypted or is not a database’.
We've created <a href="https://github.com/Azure-Samples/app-service-mobile-dotnet-offline-encryption" target="_blank">a sample on GitHub</a> that includes a solution for Xamarion.iOS and Universal Windows (UWP). The same technique will also work with Xamarin.Forms applications.
<h3>Useful links</h3>
<ul>
<li><a href="https://www.sqlite.org/see/doc/trunk/www/readme.wiki" target="_blank">How to compile and use SEE</a>.</li>
<li><a href="https://www.sqlite.org/see/doc/trunk/www/readme.wiki" target="_blank">Build and use the CLI for SEE</a> for additional options. For example, You can update/remove password for encrypted database using the rekey option.</li>
<li>How to <a href="http://www.mono-project.com/docs/advanced/pinvoke/" target="_blank">Interop with Native Libraries in Xamarin</a>.</li>
</ul>
<h3>Tips</h3>
The <a href="https://developer.xamarin.com/guides/android/deployment,_testing,_and_metrics/android_debug_log/" target="_blank">Android Debug Log</a> shows detailed logs on location of the assemblies being loaded into the application. You can use this to verify the sqliteX that you built is loaded into the app.
For Xamarin.Android, set the build configuration to match the native library architecture. A mismatch in the architecture will cause <strong>dll not found</strong> errors.
<h3>Getting in touch</h3>
As always, you can ask questions of the team via <a href="http://stackoverflow.com/questions/tagged/azure-mobile-services" target="_blank">Stack Overflow</a> or the <a href="https://social.msdn.microsoft.com/forums/azure/en-US/home?forum=azuremobile&filter=alltypes&sort=lastpostdesc" target="_blank">Azure Forums</a>.</div>
</div></body>
<script src="{{ site.baseurl }}/resource/jquery-1.12.1.min.js" type="text/javascript"></script>
<script src="{{ site.baseurl }}/resource/replace.js" type="text/javascript"></script>
</html>